home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Book Chapters / 03 - Advanced Graphics / Example 7 / update.c < prev    next >
Text File  |  1995-03-10  |  7KB  |  270 lines

  1. //
  2. //    File: update.c
  3. //
  4. //    This file contains routines to manage the update from the offscreen to the screen.
  5. //
  6. //    2/19/95 -- Created by Mick
  7. //
  8.  
  9. // include files
  10.  
  11. #include "global.h"
  12.  
  13. #include "update.h"
  14.  
  15. // defines for this file
  16.  
  17. #define kMaxRects            10                // the maximum number of update rects
  18. #define kInitialRects            10                    // the initial number of update rects
  19.  
  20. // global function declarations
  21.  
  22. void clearUpdate( void );
  23. void addRectToUpdate( Rect *inUpdateRect );
  24. unsigned long getUpdateRectCount( void );
  25. void getUpdateRect( unsigned long inRectIndex, Rect *outUpdateRect );
  26. void increaseUpdateRects( void );
  27. void decreaseUpdateRects( void );
  28.  
  29. // global data owned by this file
  30.  
  31. // local function declarations
  32.  
  33. static void adjustRect( Rect *ioRect );
  34.  
  35. // static data
  36.  
  37. static sNumUpdateRects = kInitialRects;                                // the number of update rects
  38. static Rect sUpdateRects[ kMaxRects ];                                    // the rects that needs to be udpated
  39. static unsigned long sUpdateRectCount;                                    // how many update rects are there
  40.  
  41. // functions
  42.  
  43.  
  44. //
  45. //    clearUpdate -
  46. //
  47. //    Reset the update area to none.
  48. //
  49.  
  50. void clearUpdate( void )
  51. {
  52.     // note that there are no update rects
  53.     sUpdateRectCount = 0;
  54. }
  55.  
  56.  
  57. //
  58. //    addRectToUpdate -
  59. //
  60. //    Adds a rect to the update area.
  61. //
  62.  
  63. void addRectToUpdate( Rect *inUpdateRect )
  64. {
  65.     Rect newRect;                                                        // the rect we are adding
  66.     unsigned long indexCounter;        // a counter to scan the rect array
  67.     unsigned char xTouch;                        // do the rects intersect horizontally
  68.     unsigned char yTouch;                        // do the rects intersect vertically
  69.     unsigned long bestIndex;                    // the index of our best canidate rect
  70.     unsigned long bestArea;                        // the area of our best canidate rect
  71.     unsigned long scratchArea;                        // a temp area for calculations
  72.     Rect scratchRect;                                        // a temp rect for calculations
  73.     Rect bestRect;                                                // the best rect so far
  74.     
  75.     // adjust the rect to 32 bit bounds
  76.     newRect = *inUpdateRect;
  77.     adjustRect( &newRect );
  78.     
  79.     // scan the list and see if the rect touches any of the rects there
  80.     for( indexCounter = 0; indexCounter < sUpdateRectCount; indexCounter++ )
  81.         {
  82.             // do the rects touch?
  83.             
  84.             // check horizontally
  85.             if ( newRect.left < sUpdateRects[ indexCounter ].left )
  86.                 {
  87.                     if ( newRect.right >= sUpdateRects[ indexCounter ].left )
  88.                         {
  89.                             xTouch = kTrue;
  90.                         }
  91.                     else
  92.                         {
  93.                             xTouch = kFalse;
  94.                         }
  95.                 }
  96.             else
  97.                 {
  98.                     if ( sUpdateRects[ indexCounter ].right >= newRect.left )
  99.                         {
  100.                             xTouch = kTrue;
  101.                         }
  102.                     else
  103.                         {
  104.                             xTouch = kFalse;
  105.                         }
  106.                 }
  107.             
  108.             // check vertically
  109.             if ( newRect.top < sUpdateRects[ indexCounter ].top )
  110.                 {
  111.                     if ( newRect.bottom >= sUpdateRects[ indexCounter ].top )
  112.                         {
  113.                             yTouch = kTrue;
  114.                         }
  115.                     else
  116.                         {
  117.                             yTouch = kFalse;
  118.                         }
  119.                 }
  120.             else
  121.                 {
  122.                     if ( sUpdateRects[ indexCounter ].bottom >= newRect.top )
  123.                         {
  124.                             yTouch = kTrue;
  125.                         }
  126.                     else
  127.                         {
  128.                             yTouch = kFalse;
  129.                         }
  130.                 }
  131.             
  132.             // if the rects do touch,
  133.             if ( yTouch && xTouch )
  134.                 {
  135.                     // join the rects into new rect
  136.                     newRect.left = ( newRect.left < sUpdateRects[ indexCounter ].left ) ? newRect.left : sUpdateRects[ indexCounter ].left;
  137.                     newRect.top = ( newRect.top < sUpdateRects[ indexCounter ].top ) ? newRect.top : sUpdateRects[ indexCounter ].top;
  138.                     newRect.right = ( newRect.right > sUpdateRects[ indexCounter ].right ) ? newRect.right : sUpdateRects[ indexCounter ].right;
  139.                     newRect.bottom = ( newRect.bottom > sUpdateRects[ indexCounter ].bottom ) ? newRect.bottom : sUpdateRects[ indexCounter ].bottom;
  140.                     
  141.                     // remove the rect from the list
  142.                     sUpdateRectCount -= 1;
  143.                     for( ; indexCounter < sUpdateRectCount; indexCounter++ )
  144.                         {
  145.                             // shift the next rects down
  146.                             sUpdateRects[ indexCounter ] = sUpdateRects[ indexCounter + 1 ];
  147.                         }
  148.                     
  149.                     // call this routine with the new, joined rect
  150.                     addRectToUpdate( &newRect );
  151.                     
  152.                     // we are done
  153.                     return;
  154.                 }
  155.         }
  156.     
  157.     // if there is room, add this rect to the list
  158.     if ( sUpdateRectCount < sNumUpdateRects )
  159.         {
  160.             sUpdateRects[ sUpdateRectCount ] = newRect;
  161.             sUpdateRectCount++;
  162.         }
  163.     else
  164.         {
  165.             // otherwise find the rect where the union is the smallest
  166.             bestIndex = 0;
  167.             bestArea = 0xFFFFFFFF;                // a very big area
  168.             for( indexCounter = 0; indexCounter < sUpdateRectCount; indexCounter++ )
  169.                 {
  170.                     // create the unified rect
  171.                     scratchRect.left = ( newRect.left < sUpdateRects[ indexCounter ].left ) ? newRect.left : sUpdateRects[ indexCounter ].left;
  172.                     scratchRect.top = ( newRect.top < sUpdateRects[ indexCounter ].top ) ? newRect.top : sUpdateRects[ indexCounter ].top;
  173.                     scratchRect.right = ( newRect.right > sUpdateRects[ indexCounter ].right ) ? newRect.right : sUpdateRects[ indexCounter ].right;
  174.                     scratchRect.bottom = ( newRect.bottom > sUpdateRects[ indexCounter ].bottom ) ? newRect.bottom : sUpdateRects[ indexCounter ].bottom;
  175.                     
  176.                     // determine how much this will grow the rect
  177.                     scratchArea = ( scratchRect.right - scratchRect.left ) * ( scratchRect.bottom - scratchRect.top ) - 
  178.                             ( sUpdateRects[ indexCounter ].right - sUpdateRects[ indexCounter ].left ) * 
  179.                             ( sUpdateRects[ indexCounter ].bottom - sUpdateRects[ indexCounter ].top );
  180.                     
  181.                     // if this area is smaller than the best so far, keep it
  182.                     if ( scratchArea < bestArea )
  183.                         {
  184.                             bestArea = scratchArea;
  185.                             bestIndex = indexCounter;
  186.                             bestRect = scratchRect;
  187.                         }
  188.                 }
  189.             
  190.             // save our best canidate
  191.             sUpdateRects[ bestIndex ] = bestRect;
  192.         }
  193. }
  194.  
  195.  
  196. //
  197. //    getUpdateRectCount -
  198. //
  199. //    Get the number of update rects.
  200. //
  201.  
  202. unsigned long getUpdateRectCount( void )
  203. {
  204.     return sUpdateRectCount;
  205. }
  206.  
  207.  
  208. //
  209. //    getUpdateRect -
  210. //
  211. //    Return the update rect specified.
  212. //
  213.  
  214. void getUpdateRect( unsigned long inRectIndex, Rect *outUpdateRect )
  215. {
  216.     // return the correct rect
  217.     *outUpdateRect = sUpdateRects[ inRectIndex ];
  218. }
  219.  
  220.  
  221. //
  222. //    increaseUpdateRects -
  223. //
  224. //    Increase the number of update rects. Never go above kMaxRects.
  225. //
  226.  
  227. void increaseUpdateRects( void )
  228. {
  229.     // make sure that we are not already at the maximum
  230.     if ( sNumUpdateRects == kMaxRects )
  231.         {
  232.             return;
  233.         }
  234.     
  235.     // increase the number
  236.     sNumUpdateRects++;
  237. }
  238.  
  239.  
  240. //
  241. //    decreaseUpdateRects -
  242. //
  243. //    Decrease the number of update rects. Never go below 1.
  244. //
  245.  
  246. void decreaseUpdateRects( void )
  247. {
  248.     // make sure that we are not already at the minumum
  249.     if ( sNumUpdateRects == 1 )
  250.         {
  251.             return;
  252.         }
  253.     
  254.     // increase the number
  255.     sNumUpdateRects--;
  256. }
  257.  
  258.  
  259. //
  260. //    adjustRect -
  261. //
  262. //    Move the left and right sides to 32 bit boundrys. This will speed up CopyBits.
  263. //
  264.  
  265. void adjustRect( Rect *ioRect )
  266. {
  267.     // expand the rect so its horizontal sides are on 32 bit bounds
  268.     ioRect->left = ioRect->left & 0xfffC;
  269.     ioRect->right = ( ioRect->right + 3 ) & 0xfffC;
  270. }